package com.xmall.order.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmall.define.constants.CommonProperties;
import com.xmall.define.dict.LogStatusEnum;
import com.xmall.define.dto.log.RetryLogDto;
import com.xmall.define.request.sys.RetryLogListPageQueryRequest;
import com.xmall.order.define.constants.OrderConstants;
import com.xmall.order.define.constants.OrderProperties;
import com.xmall.order.entity.OrderRefundRetryLog;
import com.xmall.order.mapper.OrderRefundRetryLogMapper;
import com.xmall.order.service.IOrderRefundRetryLogService;
import com.xmall.order.service.other.IOrderTradeService;
import com.xmall.order.utils.ConvertUtils;
import com.xmall.timer.handler.IRetryLogTaskHandler;
import com.xmall.utils.TimerUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单退款日志 服务实现类
 */
@Service
public class OrderRefundRetryLogServiceImpl extends ServiceImpl<OrderRefundRetryLogMapper, OrderRefundRetryLog> implements IOrderRefundRetryLogService, IRetryLogTaskHandler {

    @Resource
    private IOrderTradeService orderTradeService;

    @Resource
    private OrderProperties orderProperties;

    @Resource
    private CommonProperties commonProperties;

    /**
     * 状态置为完成
     */
    @Override
    public Boolean complete(Long id) {
        return this.update(
            new OrderRefundRetryLog(LogStatusEnum.PROCESSED.getStatus()),
            new QueryWrapper<OrderRefundRetryLog>().eq("id", id).eq("log_status", LogStatusEnum.PROCESSING.getStatus()));
    }

    /**
     * 保存
     */
    @Override
    public Long save(Long refundId, BigDecimal refundAmount) {
        OrderRefundRetryLog log = new OrderRefundRetryLog();
        log.setRefundId(refundId);
        log.setRefundAmount(refundAmount);
        log.setRefundTradeNo(IdUtil.getSnowflakeNextIdStr());
        log.setNextRetryTime(DateUtil.offsetSecond(new Date(), commonProperties.getLogRetryIntervalSecondsList().get(0)));
        this.save(log);
        return log.getId();
    }

    @Override
    public String key() {
        return OrderConstants.TimerTask.ORDER_REFUND_LOG_RETRY_TASK;
    }

    @Override
    public String name() {
        return "订单退款日志任务";
    }

    @Override
    public String cron() {
        return orderProperties.getOrderRefundLogRetryCron();
    }

    @Override
    public void execute() {
        TimerUtils.retryExecute(commonProperties, this, retryLog -> orderTradeService.executeRefund(retryLog.getId()));
    }

    /**
     * 是否有异常
     */
    @Override
    public Boolean hasException() {
        return this.count(new QueryWrapper<OrderRefundRetryLog>().gt("retry_count", 0).eq("log_status", LogStatusEnum.PROCESSING.getStatus())) > 0;
    }

    @Override
    public Page<RetryLogDto> retryListPage(RetryLogListPageQueryRequest request) {
        Page<RetryLogDto> result = new Page<>();

        QueryWrapper query = new QueryWrapper();
        query.orderByDesc("retry_count");
        query.orderByDesc("create_time");

        Page<OrderRefundRetryLog> page = this.page(new Page(request.getPage(), request.getPageSize()), query);

        BeanUtils.copyProperties(page, result);

        List<RetryLogDto> retryLogDtoList = page.getRecords().stream().map(retryLog -> {
            RetryLogDto retryLogDto = ConvertUtils.RetryLogModule.INSTANCE.toDtoFromOrderRefund(retryLog);
            retryLogDto.setMeta(retryLog);
            return retryLogDto;
        }).collect(Collectors.toList());

        result.setRecords(retryLogDtoList);
        return result;
    }
}
